package com.qimu.saiyou.consumer;

import cn.hutool.json.JSONUtil;
import com.qimu.saiyou.common.ErrorCode;
import com.qimu.saiyou.config.DelayExchangeConfig;
import com.qimu.saiyou.exception.BusinessException;
import com.qimu.saiyou.model.entity.*;
import com.qimu.saiyou.model.vo.CompeteVo;
import com.qimu.saiyou.model.vo.TeamVO;
import com.qimu.saiyou.model.vo.UserVO;
import com.qimu.saiyou.service.*;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: FeiXiang
 * @Date: 2023/07/21 06:13:02
 * @Version: 1.0
 * @Description:
 */
@Component
@Slf4j
public class EndDelayQueueConsumer {
    @Resource
    private CompetitionService competitionService;
    @Resource
    private JoinCompeteService joinCompeteService;
    @Resource
    private CompeteService competeService;
    @Resource
    private TeamService teamService;
    @Resource
    private CompeteUserService competeUserService;
    @Resource
    private UserService userService;
    @Resource
    private UserPaperAnswerService userPaperAnswerService;
    @Resource
    private CompeteExamService competeExamService;
    @Resource
    private QuestionService questionService;
    @Resource
    private QuestionAnswerService questionAnswerService;
    @Resource
    private PaperQuestionService paperQuestionService;
    @Resource
    private UserPaperService userPaperService;

    @RabbitListener(queues = DelayExchangeConfig.END_DELAY_QUEUE, ackMode = "MANUAL")
    @Transactional(rollbackFor = Exception.class)
    public void endDelay(Message message, Channel channel) throws IOException {
        String body = new String(message.getBody());
        log.info("接收到赛事结束消息：" + body);
        try {
            Competition competition = JSONUtil.toBean(JSONUtil.toJsonStr(body), Competition.class);
            competition = competitionService.getById(competition.getId());
            if (ObjectUtils.anyNotNull(competition, competition.getId()) && competition.getId() > 0) {
                Long examId = competition.getExamId();
                CompeteExam competeExam = competeExamService.getById(examId);
                if (competeExam == null) {
                    throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "考试不存在");
                }
                competeExam.setState("finish");   //赛事结束把试卷打开
                competeExamService.updateById(competeExam);
                List<UserPaper> updateUserPaper = new ArrayList<>();
                List<UserPaper> userPaperList = userPaperService.lambdaQuery().eq(UserPaper::getExamId, examId).eq(UserPaper::getCompetitionId, competition.getId()).list();
                userPaperList.forEach(userPaper -> {
                    doSumbit(userPaper, competeExam, updateUserPaper);  //批量提交
                });
                userPaperService.updateBatchById(updateUserPaper);
            }
            List<User> updatesUserList = new ArrayList<>();
            List<Compete> competeList = competeService.lambdaQuery().eq(Compete::getCompetitionId, competition.getId()).list(); //蓝方队伍 红方为伍
            List<CompeteVo> competeVoList = competeList.stream().map(this::getCompeteVo).collect(Collectors.toList());
            for (CompeteVo competeVo : competeVoList) {
                if (competeVo.getBlueScore() > competeVo.getRedScore()) {
                    TeamVO blueTeam = competeVo.getBlueTeam();
                    if (blueTeam != null) {
                        List<UserVO> teamUserList = blueTeam.getTeamUserList();
                        Competition finalCompetition = competition;
                        List<User> userList = teamUserList.stream().map(userVO -> {
                            User user = new User();
                            BeanUtils.copyProperties(userVO, user);
                            user.setUserCoin(user.getUserCoin() + Integer.parseInt(finalCompetition.getReward()));
                            return user;
                        }).collect(Collectors.toList());
                        updatesUserList.addAll(userList);
                    }
                }
                if (competeVo.getBlueScore() < competeVo.getRedScore()) {
                    TeamVO redTeam = competeVo.getRedTeam();
                    if (redTeam != null) {
                        List<UserVO> teamUserList = redTeam.getTeamUserList();
                        Competition finalCompetition = competition;
                        List<User> userList = teamUserList.stream().map(userVO -> {
                            User user = new User();
                            BeanUtils.copyProperties(userVO, user);
                            user.setUserCoin(user.getUserCoin() + Integer.parseInt(finalCompetition.getReward()));
                            return user;
                        }).collect(Collectors.toList());
                        updatesUserList.addAll(userList);//加分
                    }
                }
            }
            userService.updateBatchById(updatesUserList);
            competition.setCompetitionStatus("end");
            competitionService.updateById(competition);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error("赛事结束消息处理异常:{}", e.getMessage());
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

    private void doSumbit(UserPaper userPaper, CompeteExam competeExam, List<UserPaper> updateUserPaper) {
        // todo 结算
        List<UserPaperAnswer> newUserPaperAnswer = userPaperAnswerService.lambdaQuery()  //首先获取题库的题目
                .eq(UserPaperAnswer::getUserPaperId, userPaper.getId())
                .list();

        newUserPaperAnswer = newUserPaperAnswer.stream().filter(a -> a.getAnswerId() != null).collect(Collectors.toList());
        long sum = 0;
        for (UserPaperAnswer userPaperAnswer : newUserPaperAnswer) {
            Long questionId = userPaperAnswer.getQuestionId();
            Question question = questionService.getById(questionId);
            if (question == null) {
                continue;
            }
            PaperQuestion paperQuestion = paperQuestionService.lambdaQuery()
                    .eq(PaperQuestion::getQuestionId, question.getId())
                    .eq(PaperQuestion::getPaperId, competeExam.getPaperId()).one();
            List<QuestionAnswer> correctAnswers = questionAnswerService.lambdaQuery().eq(QuestionAnswer::getIsRight, 1).eq(QuestionAnswer::getQuestionId, question.getId()).list();
            List<Long> correctAnswerIds = correctAnswers.stream().map(QuestionAnswer::getId).sorted().collect(Collectors.toList());

            if (question.getType() == 2) {
                // 获取题目的正确答案列表
                // 获取用户的答案列表
                List<UserPaperAnswer> userAnswers = newUserPaperAnswer.stream().filter(a -> a.getQuestionId().equals(question.getId())).collect(Collectors.toList());
                // 将答案ID排序并比较
                List<Long> userAnswerIds = userAnswers.stream().map(UserPaperAnswer::getAnswerId).sorted().collect(Collectors.toList());

                // 如果答案完全匹配，则加分
                if (correctAnswerIds.equals(userAnswerIds)) {
                    sum += paperQuestion.getScore();
                }
            } else {
                if (correctAnswerIds.contains(userPaperAnswer.getAnswerId())) {
                    sum += paperQuestion.getScore();
                }
            }
        }
        userPaper.setTotalScore(sum);
        userPaper.setState("submit");
        updateUserPaper.add(userPaper);
    }


    public CompeteVo getCompeteVo(Compete compete) {
        CompeteVo competeVo = CompeteVo.objToVo(compete);
        Long blueTeamId = compete.getBlueTeamId();
        Long redTeamId = compete.getRedTeamId();
        List<Long> blueTeamIds = new ArrayList<>();
        List<Long> redTeamIds = new ArrayList<>();
        if (blueTeamId != null && blueTeamId > 0) {
            Team blueTeam = teamService.getById(blueTeamId);
            competeVo.setBlueTeam(teamService.getTeamVO(blueTeam));
            if (blueTeam != null) {
                blueTeamIds = JSONUtil.toList(blueTeam.getUsersId(), Long.class);
                long blueSum = userPaperService.lambdaQuery().in(UserPaper::getUserId, blueTeamIds).list().stream().mapToLong(UserPaper::getTotalScore).sum();
                competeVo.setBlueScore(blueSum);
            }
            if (redTeamId != null && redTeamId > 0) {
                Team redTeam = teamService.getById(redTeamId);
                competeVo.setRedTeam(teamService.getTeamVO(redTeam));
                if (redTeam != null) {
                    redTeamIds = JSONUtil.toList(redTeam.getUsersId(), Long.class);
                    long redSum = userPaperService.lambdaQuery().in(UserPaper::getUserId, redTeamIds).list().stream().mapToLong(UserPaper::getTotalScore).sum();
                    competeVo.setRedScore(redSum);
                }
            }
        }
        return competeVo;
    }
}
